package logic

import (
	"context"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"gozerogateway/common/errorx"
	"gozerogateway/rpc/common"
	"gozerogateway/rpc/model/svcmodel"
	"strings"

	"errors"
	"gozerogateway/rpc/svc/internal/svc"
	"gozerogateway/rpc/svc/svcclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type ServiceAddGrpcLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewServiceAddGrpcLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ServiceAddGrpcLogic {
	return &ServiceAddGrpcLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *ServiceAddGrpcLogic) ServiceAddGrpc(in *svcclient.ServiceAddGrpcReq) (*svcclient.ServiceAddGrpcResp, error) {
	// todo: add your logic here and delete this line
	//grpc tcp tcp+grpc
	if err := l.svcCtx.SvcGrpcModel.FindOneByServiceName(l.ctx, in.ServiceName); err == nil {
		return nil, errorx.NewDefaultError("servicename is exist")
	}
	if err := l.svcCtx.SvcGrpcModel.FindOneByPort(l.ctx, in.Port); err == nil {
		return nil, errorx.NewDefaultError("grpc table Port is already use")
	}
	if err := l.svcCtx.SvcTcpModel.FindOneByPort(l.ctx, in.Port); err == nil {
		return nil, errorx.NewDefaultError("tcp table Port is already use")
	}
	if len(strings.Split(in.IpList, ",")) != len(strings.Split(in.WeightList, ",")) {
		return nil, errorx.NewDefaultError("input iplist num != weightlist num")
	}
	if errtrans := l.svcCtx.SvcHttpModel.TransCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		_, errGrpcInfoTableTransInsert := l.svcCtx.SvcModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceInfo{
			ServiceName: in.ServiceName,
			ServiceDesc: in.ServiceDesc,
			LoadType:    common.LoadTypeGRPC,
		})
		if errGrpcInfoTableTransInsert != nil {
			return errGrpcInfoTableTransInsert
		}
		res, errGrpcTransFindIdByServiceName := l.svcCtx.SvcModel.TransFindIdByServiceName(l.ctx, session, in.ServiceName)
		if errGrpcTransFindIdByServiceName != nil {
			return errorx.NewDefaultError("(grpc) find id by servicename is error")
		}

		_, errGrpcAccessControlTableTransInsert := l.svcCtx.SvcAccessControlModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceAccessControl{
			ServiceId:         res.Id,
			OpenAuth:          in.OpenAuth,
			BlackList:         in.BlackList,
			WhiteList:         in.WhiteList,
			WhiteHostName:     in.WhiteHostName,
			ClientipFlowLimit: in.ClientIPFlowLimit,
			ServiceFlowLimit:  in.ServiceFlowLimit,
		})
		if errGrpcAccessControlTableTransInsert != nil {
			return errGrpcAccessControlTableTransInsert
		}

		_, errGrpcLoadBalanceTableTransInsert := l.svcCtx.SvcLoadBalanceModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceLoadBalance{
			ServiceId:  res.Id,
			RoundType:  in.RoundType,
			IpList:     in.IpList,
			WeightList: in.WeightList,
			ForbidList: in.ForbidList,
		})
		if errGrpcLoadBalanceTableTransInsert != nil {
			return errGrpcLoadBalanceTableTransInsert
		}

		_, errGrpcRuleTableTransInsert := l.svcCtx.SvcGrpcModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceGrpcRule{
			ServiceId:      res.Id,
			Port:           in.Port,
			HeaderTransfor: in.HeaderTransfor, //add h1 v1
		})
		if errGrpcRuleTableTransInsert != nil {
			return errGrpcRuleTableTransInsert
		}

		//
		//_,err_gatewayservicegrpcrule_update := l.svcCtx.SvcModel.Update(l.ctx, &svcmodel.GatewayServiceInfo{
		//	ServiceName: in.ServiceName,
		//	ServiceDesc: in.ServiceDesc,
		//})
		////return err_gatewayservicegrpcrule_update

		return nil
	}); errtrans != nil {
		return nil, errors.New("trans add http table error")
	}

	return &svcclient.ServiceAddGrpcResp{}, nil
}
